home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / diskBoot.OpenProm / fsDisk.c < prev    next >
C/C++ Source or Header  |  1992-05-07  |  15KB  |  429 lines

  1. /* 
  2.  * fsDisk.c --
  3.  *
  4.  *    Routines related to managing local disks.  Each partition of a local
  5.  *    disk (partitions are defined by a table on the disk header) is
  6.  *    called a ``domain''.  FsAttachDisk attaches a domain into the file
  7.  *    system, and FsDeattachDisk removes it.  A domain is given
  8.  *    a number the first time it is ever attached.  This is recorded on
  9.  *    the disk so it doesn't change between boots.  The domain number is
  10.  *    used to identify disks, and a domain number plus a file number is
  11.  *    used to identify files.  Fsdm_DomainFetch is used to get the state
  12.  *    associated with a disk, and Fsdm_DomainRelease releases the reference
  13.  *    on the state.  FsDetachDisk checks the references on domains in
  14.  *    the normal (non-forced) case so that active disks aren't detached.
  15.  *
  16.  * Copyright 1987 Regents of the University of California
  17.  * All rights reserved.
  18.  * Permission to use, copy, modify, and distribute this
  19.  * software and its documentation for any purpose and without
  20.  * fee is hereby granted, provided that the above copyright
  21.  * notice appear in all copies.  The University of California
  22.  * makes no representations about the suitability of this
  23.  * software for any purpose.  It is provided "as is" without
  24.  * express or implied warranty.
  25.  */
  26.  
  27. #ifdef notdef
  28. static char rcsid[] = "$Header: /sprite/src/boot/diskBoot.OpenProm/RCS/fsDisk.c,v 1.12 90/11/27 11:17:33 jhh Exp $ SPRITE (Berkeley)";
  29. #endif not lint
  30.  
  31.  
  32. #include "sprite.h"
  33.  
  34. #include "fsBoot.h"
  35. #include "devDiskLabel.h"
  36. #include "dev.h"
  37. #include "devFsOpTable.h"
  38. #include "machMon.h"
  39. #include "ofs.h"
  40. /*
  41.  * fsDevice is copied into all Fsio_FileIOHandles.  It is used by the drivers
  42.  * to get to the partition and geometry information for the disk.
  43.  */
  44. Fs_Device fsDevice;
  45.  
  46. /*
  47.  * fsDomainPtr and fsRootHandlePtr are used by Fs_Open.
  48.  */
  49. static Fsdm_Domain fsDomain;
  50. Fsdm_Domain *fsDomainPtr = &fsDomain;
  51. static Fsio_FileIOHandle fsRootHandle;
  52. Fsio_FileIOHandle *fsRootHandlePtr = &fsRootHandle;
  53.  
  54. /*
  55.  * Forward declarations.
  56.  */
  57. static int    InstallLocalDomain();
  58. void        AddDomainFlags();
  59. static Boolean    IsSunLabel();
  60. static Boolean    IsSpriteLabel();
  61.  
  62. /*
  63.  *----------------------------------------------------------------------
  64.  *
  65.  * FsAttachDisk --
  66.  *
  67.  *    Make a particular local disk partition correspond to a prefix.
  68.  *    This makes sure the disk is up, reads the domain header,
  69.  *    and calls the initialization routine for the block I/O module
  70.  *    of the disk's driver.  By the time this is called the device
  71.  *    initialization routines have already been called from Dev_Config
  72.  *    so the device driver knows how the disk is partitioned into
  73.  *    domains.  This routine sees if the domain is formatted correctly,
  74.  *    and if so attaches it to the set of domains.
  75.  *
  76.  * Results:
  77.  *    SUCCESS if the disk was readable and had a good domain header.
  78.  *
  79.  * Side effects:
  80.  *    Sets up the Fsdm_DomainInfo for the domain.
  81.  *
  82.  *----------------------------------------------------------------------
  83.  */
  84. ReturnStatus
  85. FsAttachDisk(fsDevicePtr)
  86.     Fs_Device *fsDevicePtr;        /* Global FS device descriptor */
  87. {
  88.     ReturnStatus status;        /* Error code */
  89.     register Address buffer;        /* Read buffer */
  90.     int headerSector;            /* Starting sector of domain header */
  91.     int numHeaderSectors;        /* Number of sectors in domain header */
  92.     int summarySector;            /* Sector of summary information. */
  93.     Ofs_SummaryInfo *summaryInfoPtr;    /* Pointer to summary info. */
  94.     int amountRead;            /* Returned from read call */
  95.     int devType;            /* Device type index */
  96.     Fs_IOParam    io;            /* I/O Parameter block */
  97.     Fs_IOReply    reply;            /* Results of I/O */
  98.     int flags;
  99.  
  100.     /*
  101.      * Open the raw disk device so we can grub around in the header info.
  102.      */
  103.     devType = DEV_TYPE_INDEX(fsDevicePtr->type);
  104.     status = (*devFsOpTable[devType].open)(&fsDevice, FS_READ, 0, &flags);
  105.     if (status != SUCCESS) {
  106.     return(status);
  107.     }
  108.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR);
  109.  
  110.     /*
  111.      * Read the zero'th sector of the partition.  It has a copy of the
  112.      * zero'th sector of the whole disk which describes how the rest of the
  113.      * domain's zero'th cylinder is layed out.
  114.      */
  115.     io.offset = 0;
  116.     io.length = DEV_BYTES_PER_SECTOR;
  117.     io.buffer = buffer;
  118.     status = (*devFsOpTable[devType].read)(&fsDevice, &io, &reply);
  119.     if (status != SUCCESS) {
  120.     return(status);
  121.     }
  122.     /*
  123.      * Check for different disk formats, and figure out how the rest
  124.      * of the zero'th cylinder is layed out.
  125.      */
  126.     if (((Sun_DiskLabel *)buffer)->magic == SUN_DISK_MAGIC) {
  127.     Ofs_DomainHeader    *domainHeaderPtr = (Ofs_DomainHeader *) buffer;
  128.     int            i;
  129.     /*
  130.      * For Sun formatted disks we put the domain header well past
  131.      * the disk label and the boot program.
  132.      */
  133.     numHeaderSectors = OFS_NUM_DOMAIN_SECTORS;
  134.     for (i = 2; i < FSDM_MAX_BOOT_SECTORS + 3; i+= FSDM_BOOT_SECTOR_INC) {
  135.         io.offset = i * DEV_BYTES_PER_SECTOR;
  136.         io.length = DEV_BYTES_PER_SECTOR * OFS_NUM_DOMAIN_SECTORS;
  137.         io.buffer = buffer;
  138.         status = (*devFsOpTable[devType].read)(&fsDevice, &io, &reply);
  139.         if (status != SUCCESS) {
  140.         return(status);
  141.         }
  142.         if (domainHeaderPtr->magic == OFS_DOMAIN_MAGIC) {
  143.         headerSector = i;
  144.         summarySector = i - 1;
  145.             break;
  146.         }
  147.     }
  148.     if (i >= FSDM_MAX_BOOT_SECTORS + 3) {
  149.         printf("Fsdm_AttachDisk: Can't find domain header.\n");
  150.         return(FAILURE);
  151.     }
  152.     } else {
  153.     printf("Disk label has bad magic number 0x%x\n", 
  154.         ((Sun_DiskLabel *)buffer)->magic);
  155.     return FAILURE;
  156.     }
  157.     ((Ofs_DomainHeader *) fsDomainPtr->clientData) = 
  158.     (Ofs_DomainHeader *) buffer;
  159.  
  160.      /*
  161.      * Set up the ClientData part of *devicePtr to reference the
  162.      * Ofs_Geometry part of the domain header.  This is used by the
  163.      * block I/O routines.
  164.      */
  165.     fsDevicePtr->data = (ClientData)
  166.     &((Ofs_DomainHeader *) fsDomainPtr->clientData)->geometry;
  167.  
  168.     /*
  169.      * Set up a file handle for the root directory.  What is important
  170.      * is the device info (for Block IO) and the file descriptor itself.
  171.      */
  172.     FsInitFileHandle(fsDomainPtr, FSDM_ROOT_FILE_NUMBER, fsRootHandlePtr);
  173.     return(SUCCESS);
  174. }
  175.  
  176. /*
  177.  *----------------------------------------------------------------------
  178.  * The following routines are used by device drivers to map from block
  179.  * and sector numbers to disk addresses.  There are two sets, one for
  180.  * drivers that use logical sector numbers (i.e. SCSI) and the other
  181.  * for <cyl,head,sector> format disk addresses.
  182.  *----------------------------------------------------------------------
  183.  */
  184.  
  185. /*
  186.  *----------------------------------------------------------------------
  187.  *
  188.  * Fs_BlocksToSectors --
  189.  *
  190.  *    Convert from block indexes (actually, fragment indexes) to
  191.  *    sectors using the geometry information on the disk.  This
  192.  *    is a utility for block device drivers.
  193.  *
  194.  * Results:
  195.  *    The sector number that corresponds to the fragment index.
  196.  *    The caller has to make sure that its I/O doesn't cross a
  197.  *    filesystem block boundary.
  198.  *
  199.  * Side effects:
  200.  *    None.
  201.  *
  202.  *----------------------------------------------------------------------
  203.  */
  204. #define SECTORS_PER_FRAG    (FS_FRAGMENT_SIZE / DEV_BYTES_PER_SECTOR)
  205. #if defined(SCSI_DISK_BOOT) || defined(SUN_PROM_BOOT)
  206. int
  207. Fs_BlocksToSectors(fragNumber, data)
  208.     int fragNumber;    /* Fragment index to map into block index */
  209.     ClientData data;    /* ClientData from the device info */
  210. {
  211.     register Ofs_Geometry *geoPtr;
  212.     register int sectorNumber;    /* The sector corresponding to the fragment */
  213.     register int cylinder;    /* The cylinder number of the fragment */
  214.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  215.     register int blockNumber;    /* The block number within rotational set */
  216.  
  217.     geoPtr         = (Ofs_Geometry *)data;
  218.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  219.     if (geoPtr->blocksPerCylinder == 0) {
  220.     panic("blocksPerCylinder is 0");
  221.     }
  222.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  223.     if (geoPtr->rotSetsPerCyl > 0) {
  224.     /*
  225.      * Do fancy rotational set mapping.
  226.      */
  227.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  228.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  229.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  230.  
  231.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  232.               geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  233.               rotationalSet +
  234.               geoPtr->blockOffset[blockNumber];
  235.     sectorNumber += (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  236.     } else {
  237.     /*
  238.      * Do straight-forward mapping.
  239.      */
  240.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  241.             fragNumber * SECTORS_PER_FRAG - cylinder * 
  242.             geoPtr->blocksPerCylinder * FS_FRAGMENTS_PER_BLOCK *
  243.             SECTORS_PER_FRAG;
  244.     }
  245.  
  246.     return(sectorNumber);
  247. }
  248. #endif
  249.  
  250. /*
  251.  *----------------------------------------------------------------------
  252.  *
  253.  * Fs_BlocksToDiskAddr --
  254.  *
  255.  *    Convert from block indexes (actually, fragment indexes) to
  256.  *    disk address (head, cylinder, sector) using the geometry information
  257.  *     on the disk.  This is a utility for block device drivers.
  258.  *
  259.  * Results:
  260.  *    The disk address that corresponds to the disk address.
  261.  *    The caller has to make sure that its I/O doesn't cross a
  262.  *    filesystem block boundary.
  263.  *
  264.  * Side effects:
  265.  *    None.
  266.  *
  267.  *----------------------------------------------------------------------
  268.  */
  269. #ifdef XYLOGICS_BOOT
  270. void
  271. Fs_BlocksToDiskAddr(fragNumber, data, diskAddrPtr)
  272.     int fragNumber;    /* Fragment index to map into block index */
  273.     ClientData data;    /* ClientData from the device info */
  274.     Dev_DiskAddr *diskAddrPtr;
  275. {
  276.     register Ofs_Geometry *geoPtr;
  277.     register int sectorNumber;    /* The sector corresponding to the fragment */
  278.     register int cylinder;    /* The cylinder number of the fragment */
  279.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  280.     register int blockNumber;    /* The block number within rotational set */
  281.  
  282.     geoPtr         = (Ofs_Geometry *)data;
  283.     /*
  284.      * Map to block number because the rotational sets are laid out
  285.      * relative to blocks.  After that the cylinder is easy because we know
  286.      * blocksPerCylinder.  To get the head and sector we first get the
  287.      * rotational set (described in fsDisk.h) of the block and the
  288.      * block's sector offset (relative to the rotational set!).  This complex
  289.      * algorithm crops up because there isn't necessarily an even number
  290.      * of blocks per track.  The 'blockOffset' array in the geometry gives
  291.      * a sector index of each successive block in a rotational set. Finally,
  292.      * we can use the sectorsPerTrack to get the head and sector.
  293.      */
  294.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  295.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  296.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  297.     diskAddrPtr->cylinder = cylinder;
  298.  
  299.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  300.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  301. /*
  302.  * The follow statment had to be broken into two because the compiler used
  303.  * register d2 to do the modulo operation, but wasn't saving its value.
  304.  */
  305.     sectorNumber    = geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  306.               rotationalSet + geoPtr->blockOffset[blockNumber];
  307.     sectorNumber    +=
  308.             (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  309.  
  310.     diskAddrPtr->head    = sectorNumber / geoPtr->sectorsPerTrack;
  311.     diskAddrPtr->sector = sectorNumber -
  312.               diskAddrPtr->head * geoPtr->sectorsPerTrack;
  313. }
  314. #endif
  315.  
  316. /*
  317.  *----------------------------------------------------------------------
  318.  *
  319.  * Fs_SectorsToRawDiskAddr --
  320.  *
  321.  *      Convert from a sector offset to a raw disk address (cyl, head,
  322.  *      sector) using the geometry information on the disk.  This is a
  323.  *      utility for raw device drivers and does not pay attention to the
  324.  *      rotational position of filesystem disk blocks.
  325.  *
  326.  *    This should be moved to Dev
  327.  *
  328.  * Results:
  329.  *    The disk address that corresponds exactly to the byte offset.
  330.  *
  331.  * Side effects:
  332.  *    None.
  333.  *
  334.  *----------------------------------------------------------------------
  335.  */
  336. #ifdef XYLOGICS_BOOT
  337. int
  338. Fs_SectorsToRawDiskAddr(sector, numSectors, numHeads, diskAddrPtr)
  339.     int sector;        /* Sector number (counting from zero 'til the total
  340.              * number of sectors in the disk) */
  341.     int numSectors;    /* Number of sectors per track */
  342.     int numHeads;    /* Number of heads on the disk */
  343.     Dev_DiskAddr *diskAddrPtr;
  344. {
  345.     register int sectorsPerCyl;    /* The rotational set with cylinder of frag */
  346.  
  347.     sectorsPerCyl        = numSectors * numHeads;
  348.     diskAddrPtr->cylinder    = sector / sectorsPerCyl;
  349.     sector            -= diskAddrPtr->cylinder * sectorsPerCyl;
  350.     diskAddrPtr->head        = sector / numSectors;
  351.     diskAddrPtr->sector        = sector - numSectors * diskAddrPtr->head;
  352. }
  353. #endif
  354.  
  355.  
  356. /*
  357.  *----------------------------------------------------------------------
  358.  *
  359.  * FsDeviceBlockIO --
  360.  *
  361.  *    Map a file system block address to a block device block address 
  362.  *    perform the requested operation.
  363.  *
  364.  * NOTE: This routine is temporary and should be replaced when the file system
  365.  *     is converted to use the async block io interface.
  366.  *
  367.  * Results:
  368.  *    The return status of the operation.
  369.  *
  370.  * Side effects:
  371.  *    Blocks may be written or read.
  372.  *
  373.  *----------------------------------------------------------------------
  374.  */
  375.  
  376. ReturnStatus
  377. FsDeviceBlockIO(readWriteFlag, devicePtr, fragNumber, numFrags, buffer)
  378.     int readWriteFlag;        /* FS_READ or FS_WRITE */
  379.     Fs_Device *devicePtr;    /* Specifies device type to do I/O with */
  380.     int fragNumber;        /* CAREFUL, fragment index, not block index.
  381.                  * This is relative to start of device. */
  382.     int numFrags;        /* CAREFUL, number of fragments, not blocks */
  383.     Address buffer;        /* I/O buffer */
  384. {
  385.     ReturnStatus status;    /* General return code */
  386.     int firstSector;        /* Starting sector of transfer */
  387.     DevBlockDeviceRequest    request;
  388.     int                transferCount;
  389.     int                devType;
  390.     Fs_IOParam            io;        
  391.     Fs_IOReply            reply;    
  392.  
  393.     devType = DEV_TYPE_INDEX(devicePtr->type);
  394.     if ((fragNumber % FS_FRAGMENTS_PER_BLOCK) != 0) {
  395.     /*
  396.      * The I/O doesn't start on a block boundary.  Transfer the
  397.      * first few extra fragments to get things going on a block boundary.
  398.      */
  399.     register int extraFrags;
  400.  
  401.     extraFrags = FS_FRAGMENTS_PER_BLOCK -
  402.             (fragNumber % FS_FRAGMENTS_PER_BLOCK);
  403.     if (extraFrags > numFrags) {
  404.         extraFrags = numFrags;
  405.     }
  406.     firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
  407.     io.offset = firstSector * DEV_BYTES_PER_SECTOR;
  408.     io.length = extraFrags * FS_FRAGMENT_SIZE;
  409.     io.buffer = buffer;
  410.     status = (*devFsOpTable[devType].read)(devicePtr, &io, &reply);
  411.     extraFrags = reply.length / FS_FRAGMENT_SIZE;
  412.     fragNumber += extraFrags;
  413.     buffer += reply.length;
  414.     numFrags -= extraFrags;
  415.     }
  416.     if (numFrags > 0) {
  417.     /*
  418.      * Transfer the left over fragments.
  419.      */
  420.     firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
  421.     io.offset = firstSector * DEV_BYTES_PER_SECTOR;
  422.     io.length = numFrags * FS_FRAGMENT_SIZE;
  423.     io.buffer = buffer;
  424.     status = (*devFsOpTable[devType].read)(devicePtr, &io, &reply);
  425.     }
  426.     return(status);
  427. }
  428.  
  429.